/*******************************************************************
 *
 * Copyright (C), 2021-2022, Letstrong, All rights reserved.
 *
 * Author      : 
 * Create Time : 2020-12-12
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "hal_gpio.h"
#include "user_config.h"
#include "icu.h"
#include "intc.h"
#include "string.h"
#include "stdbool.h"

/*----------------------------macro file---------------------------*/
#if (BUTTON_NUM > 0)
#define GPIO_IN_MAX_NUM		(BUTTON_NUM + HALL_NUM)
#else
#define GPIO_IN_MAX_NUM		1
#endif

#define hal_gpio_int_status_get(pin_num)	( REG_APB5_GPIO_WUATOD_STAT & ( 1<<(8*(pin_num>>4)+(pin_num&0x0f)) ) )
#define hal_gpio_int_status_clr(pin_num)	(REG_APB5_GPIO_WUATOD_STAT |= 1<<(8*(pin_num>>4)+(pin_num&0x0f)))
#define hal_gpio_int_status_clr_all()		(REG_APB5_GPIO_WUATOD_STAT = 0xffffffff)

/*----------------------------type define--------------------------*/
typedef struct {
	uint8_t					pin_num;
	uint8_t					edge;
	hal_gpio_int_evt_cb		cb;
} hal_gpio_in_cfg_t;

typedef struct {
	uint8_t					set_num;
	hal_gpio_in_cfg_t		cfg[GPIO_IN_MAX_NUM];
} hal_gpio_in_set_t;
/*----------------------------var define---------------------------*/
static hal_gpio_in_set_t	in_gpio_set;

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/

static void hal_gpio_int_cb(void)
{
	for(uint8_t i=0;i<in_gpio_set.set_num;i++) {
		if(hal_gpio_int_status_get(in_gpio_set.cfg[i].pin_num)) {
			if(in_gpio_set.cfg[i].cb) {
				in_gpio_set.cfg[i].cb(in_gpio_set.cfg[i].pin_num);
			}
		}
	}
	
	hal_gpio_int_status_clr_all();
}

void hal_gpio_init(void)
{
	REG_APB5_GPIO_WUATOD_ENABLE = 0x00000000; 
	REG_APB5_GPIO_WUATOD_STAT = 0x00000000;
	gpio_cb_register(hal_gpio_int_cb);
}

void hal_gpio_int_enable(uint8_t pin_num, hal_gpio_int_edge_t edge, hal_gpio_int_evt_cb evt_cb)
{
	if(RAISING_EDGE == edge) {
		REG_APB5_GPIO_WUATOD_TYPE &= (~(1<<(8*(pin_num>>4)+(pin_num&0x0f)))); //Raise up wake up.
	}
	else {
		REG_APB5_GPIO_WUATOD_TYPE |= 1<<(8*(pin_num>>4)+(pin_num&0x0f)); //Pull down wake up.
	}
	REG_APB5_GPIO_WUATOD_STAT |= 1<<(8*(pin_num>>4)+(pin_num&0x0f));
	REG_APB5_GPIO_WUATOD_ENABLE |= 1<<(8*(pin_num>>4)+(pin_num&0x0f));
	REG_AHB0_ICU_DEEP_SLEEP0 |= 1<<(8*(pin_num>>4)+(pin_num&0x0f));
	
	if(in_gpio_set.set_num < GPIO_IN_MAX_NUM) {
		in_gpio_set.cfg[in_gpio_set.set_num].pin_num	= pin_num;
		in_gpio_set.cfg[in_gpio_set.set_num].edge 		= edge;
		in_gpio_set.cfg[in_gpio_set.set_num].cb			= evt_cb;
		in_gpio_set.set_num++;
	}

	REG_AHB0_ICU_INT_ENABLE |= INT_GPIO_bit;
}

void hal_gpio_int_disable(uint8_t pin_num)
{
#if SYSTEM_SLEEP
	REG_APB5_GPIO_WUATOD_TYPE &= (~(1<<(8*(pin_num>>4)+(pin_num&0x0f))));
	REG_APB5_GPIO_WUATOD_STAT &= (~(1<<(8*(pin_num>>4)+(pin_num&0x0f))));
	REG_APB5_GPIO_WUATOD_ENABLE &= (~(1<<(8*(pin_num>>4)+(pin_num&0x0f))));
	REG_AHB0_ICU_DEEP_SLEEP0 &= (~(1<<(8*(pin_num>>4)+(pin_num&0x0f))));
#endif
}


